home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / Net / IPv4.php < prev    next >
PHP Script  |  2004-10-01  |  13KB  |  394 lines

  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2003 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Eric Kilfoil <eric@ypass.net>                               |
  17. // +----------------------------------------------------------------------+
  18. //
  19.  
  20. require_once("PEAR.php");
  21.  
  22. /**
  23.  * Map of bitmasks to subnets
  24.  *
  25.  * This array contains every valid netmask.  The index of the dot quad
  26.  * netmask value is the corresponding CIDR notation (bitmask).
  27.  */
  28. $GLOBALS['Net_IPv4_Netmask_Map'] = array(
  29.             0 => "0.0.0.0",
  30.             1 => "128.0.0.0",
  31.             2 => "192.0.0.0",
  32.             3 => "224.0.0.0",
  33.             4 => "240.0.0.0",
  34.             5 => "248.0.0.0",
  35.             6 => "252.0.0.0",
  36.             7 => "254.0.0.0",
  37.             8 => "255.0.0.0",
  38.             9 => "255.128.0.0",
  39.             10 => "255.192.0.0",
  40.             11 => "255.224.0.0",
  41.             12 => "255.240.0.0",
  42.             13 => "255.248.0.0",
  43.             14 => "255.252.0.0",
  44.             15 => "255.254.0.0",
  45.             16 => "255.255.0.0",
  46.             17 => "255.255.128.0",
  47.             18 => "255.255.192.0",
  48.             19 => "255.255.224.0",
  49.             20 => "255.255.240.0",
  50.             21 => "255.255.248.0",
  51.             22 => "255.255.252.0",
  52.             23 => "255.255.254.0",
  53.             24 => "255.255.255.0",
  54.             25 => "255.255.255.128",
  55.             26 => "255.255.255.192",
  56.             27 => "255.255.255.224",
  57.             28 => "255.255.255.240",
  58.             29 => "255.255.255.248",
  59.             30 => "255.255.255.252",
  60.             31 => "255.255.255.254",
  61.             32 => "255.255.255.255"
  62.         );
  63.  
  64.  
  65. /**
  66. * Class to provide IPv4 calculations
  67. *
  68. * Provides methods for validating IP addresses, calculating netmasks,
  69. * broadcast addresses, network addresses, conversion routines, etc.
  70. *
  71. * @author  Eric Kilfoil <edk@ypass.net>
  72. * @package Net_IPv4
  73. * @version 1.0
  74. * @access  public
  75. */
  76. class Net_IPv4
  77. {
  78.     var $ip = "";
  79.     var $bitmask = false;
  80.     var $netmask = "";
  81.     var $network = "";
  82.     var $broadcast = "";
  83.     var $long = 0;
  84.  
  85.     /**
  86.      * Validate the syntax of the given IP adress
  87.      *
  88.      * Using the PHP long2ip() and ip2long() functions, convert the IP
  89.      * address from a string to a long and back.  If the original still
  90.      * matches the converted IP address, it's a valid address.  This
  91.      * function does not allow for IP addresses to be formatted as long
  92.      * integers.
  93.      *
  94.      * @param  string $ip IP address in the format x.x.x.x
  95.      * @return bool       true if syntax is valid, otherwise false
  96.      */
  97.     function validateIP($ip)
  98.     {
  99.         if ($ip == long2ip(ip2long($ip))) {
  100.             return(TRUE);
  101.         } else {
  102.             return(FALSE);
  103.         }
  104.     }
  105.  
  106.     /**
  107.      * Validate the syntax of the given IP address (compatibility)
  108.      *
  109.      * This function is identical to Net_IPv4::validateIP().  It is included
  110.      * merely for compatibility reasons.
  111.      *
  112.      * @param  string $ip IP address
  113.      * @return bool       true if syntax is valid, otherwise false
  114.      */
  115.     function check_ip($ip)
  116.     {
  117.         return($this->validateIP($ip));
  118.     }
  119.  
  120.     /**
  121.      * Validate the syntax of a four octet netmask
  122.      *
  123.      * There are 33 valid netmask values.  This function will compare the
  124.      * string passed as $netmask to the predefined 33 values and return
  125.      * true or false.  This is most likely much faster than performing the
  126.      * calculation to determine the validity of the netmask.
  127.      *
  128.      * @param  string $netmask Netmask
  129.      * @return bool       true if syntax is valid, otherwise false
  130.      */
  131.     function validateNetmask($netmask)
  132.     {
  133.         if (! in_array($netmask, $GLOBALS['Net_IPv4_Netmask_Map'])) {
  134.             return(FALSE);
  135.         }
  136.         return(TRUE);
  137.     }
  138.  
  139.     /**
  140.      * Parse a formatted IP address
  141.      *
  142.      * Given a network qualified IP address, attempt to parse out the parts
  143.      * and calculate qualities of the address.
  144.      *
  145.      * The following formats are possible:
  146.      *
  147.      * [dot quad ip]/[ bitmask ]
  148.      * [dot quad ip]/[ dot quad netmask ]
  149.      * [dot quad ip]/[ hex string netmask ]
  150.      *
  151.      * The first would be [IP Address]/[BitMask]:
  152.      * 192.168.0.0/16
  153.      *
  154.      * The second would be [IP Address] [Subnet Mask in quad dot notation]:
  155.      * 192.168.0.0/255.255.0.0
  156.      *
  157.      * The third would be [IP Address] [Subnet Mask as Hex string]
  158.      * 192.168.0.0/ffff0000
  159.      *
  160.      * Usage:
  161.      *
  162.      * $cidr = '192.168.0.50/16';
  163.      * $net = Net_IPv4::parseAddress($cidr);
  164.      * echo $net->network; // 192.168.0.0
  165.      * echo $net->ip; // 192.168.0.50
  166.      * echo $net->broadcast; // 192.168.255.255
  167.      * echo $net->bitmask; // 16
  168.      * echo $net->long; // 3232235520 (long/double version of 192.168.0.50)
  169.      * echo $net->netmask; // 255.255.0.0
  170.      *
  171.      * @param  string $ip IP address netmask combination
  172.      * @return object     true if syntax is valid, otherwise false
  173.      */
  174.     function parseAddress($address)
  175.     {
  176.         $myself = new Net_IPv4;
  177.         if (strchr($address, "/")) {
  178.             $parts = explode("/", $address);
  179.             if (! $myself->validateIP($parts[0])) {
  180.                 return(PEAR::raiseError("invalid IP address"));
  181.             }
  182.             $myself->ip = $parts[0];
  183.  
  184.             // Check the style of netmask that was entered 
  185.             /*
  186.              *  a hexadecimal string was entered
  187.              */
  188.             if (eregi("^([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$", $parts[1], $regs)) {
  189.                 // hexadecimal string
  190.                 $myself->netmask = hexdec($regs[1]) . "." .  hexdec($regs[2]) . "." .
  191.                     hexdec($regs[3]) . "." .  hexdec($regs[4]);
  192.  
  193.             /*
  194.              *  a standard dot quad netmask was entered.
  195.              */
  196.             } else if (strchr($parts[1], ".")) {
  197.                 if (! $myself->validateNetmask($parts[1])) {
  198.                     return(PEAR::raiseError("invalid netmask value"));
  199.                 }
  200.                 $myself->netmask = $parts[1];
  201.  
  202.             /*
  203.              *  a CIDR bitmask type was entered
  204.              */
  205.             } else if ($parts[1] >= 0 && $parts[1] <= 32) {
  206.                 // bitmask was entered
  207.                 $myself->bitmask = $parts[1];
  208.  
  209.             /*
  210.              *  Some unknown format of netmask was entered
  211.              */
  212.             } else {
  213.                 return(PEAR::raiseError("invalid netmask value"));
  214.             }
  215.             $myself->calculate();
  216.             return($myself);
  217.         } else if ($myself->validateIP($address)) {
  218.             $myself->ip = $address;
  219.             return($myself);
  220.         } else {
  221.             return(PEAR::raiseError("invalid IP address"));
  222.         }
  223.     }
  224.     
  225.     /**
  226.      * Calculates network information based on an IP address and netmask.
  227.      *
  228.      * Fully populates the object properties based on the IP address and
  229.      * netmask/bitmask properties.  Once these two fields are populated,
  230.      * calculate() will perform calculations to determine the network and
  231.      * broadcast address of the network.
  232.      *
  233.      * @return mixed     true if no errors occured, otherwise PEAR_Error object
  234.      */
  235.     function calculate() {
  236.         $validNM = $GLOBALS['Net_IPv4_Netmask_Map'];
  237.  
  238.         if (! is_a($this, "net_ipv4")) {
  239.             $myself = new Net_IPv4;
  240.             return(PEAR::raiseError("cannot calculate on uninstantiated Net_IPv4 class"));
  241.         }
  242.  
  243.         /* Find out if we were given an ip address in dot quad notation or
  244.          * a network long ip address.  Whichever was given, populate the
  245.          * other field
  246.          */
  247.         if (strlen($this->ip)) {
  248.             if (! $this->validateIP($this->ip)) {
  249.                 return(PEAR::raiseError("invalid IP address"));
  250.             }
  251.             $this->long = $this->ip2double($this->ip);
  252.         } else if (is_numeric($this->long)) {
  253.             $this->ip = long2ip($this->long);
  254.         } else {
  255.            return(PEAR::raiseError("ip address not specified"));
  256.         }
  257.  
  258.         /*
  259.          * Check to see if we were supplied with a bitmask or a netmask.
  260.          * Populate the other field as needed.
  261.          */
  262.         if (strlen($this->bitmask)) {
  263.             $this->netmask = $validNM[$this->bitmask];
  264.         } else if (strlen($this->netmask)) {
  265.             $validNM_rev = array_flip($validNM);
  266.             $this->bitmask = $validNM_rev[$this->netmask];
  267.         } else {
  268.             return(PEAR::raiseError("netmask or bitmask are required for calculation"));
  269.         }
  270.         $this->network = long2ip(ip2long($this->ip) & ip2long($this->netmask));
  271.         $this->broadcast = long2ip(ip2long($this->ip) |
  272.                 (ip2long($this->netmask) ^ ip2long("255.255.255.255")));
  273.         return(TRUE);
  274.     }
  275.  
  276.     function getNetmask($length) {
  277.         if (! PEAR::isError($ipobj = Net_IPv4::parseAddress("0.0.0.0/" . $length))) {
  278.             $mask = $ipobj->netmask;
  279.             unset($ipobj);
  280.             return($mask);
  281.         }
  282.         return(FALSE);
  283.     }
  284.  
  285.     function getNetLength($netmask) {
  286.         if (! PEAR::isError($ipobj = Net_IPv4::parseAddress("0.0.0.0/" . $netmask))) {
  287.             $bitmask = $ipobj->bitmask;
  288.             unset($ipobj);
  289.             return($bitmask);
  290.         }
  291.         return(FALSE);
  292.     }
  293.  
  294.     function getSubnet($ip, $netmask) {
  295.         if (! PEAR::isError($ipobj = Net_IPv4::parseAddress($ip . "/" . $netmask))) {
  296.             $net = $ipobj->network;
  297.             unset($ipobj);
  298.             return($net);
  299.         }
  300.         return(FALSE);
  301.     }
  302.  
  303.     function inSameSubnet($ip1, $ip2) {
  304.         if (! is_object($ip1) || strtolower(get_class($ip1)) != "net_ipv4") {
  305.             $ipobj1 = Net_IPv4::parseAddress($ip1);
  306.             if (PEAR::isError($ipobj)) {
  307.                 return(PEAR::raiseError("IP addresses must be an understood format or a Net_IPv4 object"));
  308.             }
  309.         }
  310.         if (! is_object($ip2) || strtolower(get_class($ip2)) != "net_ipv4") {
  311.             $ipobj2 = Net_IPv4::parseAddress($ip2);
  312.             if (PEAR::isError($ipobj)) {
  313.                 return(PEAR::raiseError("IP addresses must be an understood format or a Net_IPv4 object"));
  314.             }
  315.         }
  316.         if ($ipobj1->network == $ipobj2->network &&
  317.                 $ipobj1->bitmask == $ipobj2->bitmask) {
  318.                 return(TRUE);
  319.         }
  320.         return(FALSE);
  321.     }
  322.  
  323.     /**
  324.      * Converts a dot-quad formmated IP address into a hexadecimal string
  325.      */
  326.     function atoh($addr)
  327.     {
  328.         if (! Net_IPv4::validateIP($addr)) {
  329.             return(FALSE);
  330.         }
  331.         $ap = explode(".", $addr);
  332.         return(sprintf("%02x%02x%02x%02x",
  333.                     $ap[0], $ap[1],
  334.                     $ap[2], $ap[3]));
  335.     }
  336.  
  337.     /**
  338.      * Converts a hexadecimal string into a dot-quad formatted IP address
  339.      */
  340.     function htoa($addr)
  341.     {
  342.         if (eregi("^([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$",
  343.                     $addr, $regs)) {
  344.             return(hexdec($regs[1]) . "." .  hexdec($regs[2]) . "." .
  345.                 hexdec($regs[3]) . "." .  hexdec($regs[4]));
  346.         }
  347.         return(FALSE);
  348.     }
  349.     /**
  350.      * Converts an IP address to a PHP double.  Better than ip2long because
  351.      * a long in PHP is a signed integer.
  352.      */
  353.     function ip2double($ip)
  354.     {
  355.         return((double)(sprintf("%u", ip2long($ip))));
  356.     }
  357.  
  358.     /**
  359.      * Determines whether or not the supplied IP is within the supplied network.
  360.      *
  361.      * This function determines whether an IP address is within a network.
  362.      * The IP address ($ip) must be supplied in dot-quad format, and the
  363.      * network ($network) may be either a string containing a CIDR
  364.      * formatted network definition, or a Net_IPv4 object.
  365.      *
  366.      * @param  string $ip A quad-dot representation of an IP address 
  367.      * @param  string $network A string representing the network in CIDR format or a Net_IPv4 object.
  368.      * @return boolean  true if the IP address exists within the network
  369.      */
  370.     function ipInNetwork($ip, $network)
  371.     {
  372.         if (! is_object($network) || get_class($network) != 'net_ipv4') {
  373.             $network = Net_IPv4::parseAddress($network);
  374.         }
  375.         if (! is_object($network) || get_class($network) != 'net_ipv4') {
  376.             return($network);
  377.         }
  378.         $net = Net_IPv4::ip2double($network->network);
  379.         $bcast = Net_IPv4::ip2double($network->broadcast);
  380.         $ip = Net_IPv4::ip2double($ip);
  381.         unset($network);
  382.         if ($ip >= $net && $ip <= $bcast) {
  383.             return(TRUE);
  384.         }
  385.         return(FALSE);
  386.         return((double)(sprintf("%u", ip2long($ip))));
  387.     }
  388. }
  389.  
  390. /*
  391.  * vim: sts=4 ts=4 sw=4 cindent fdm=marker
  392.  */
  393. ?>
  394.